﻿using System;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Collections;
using TPG.SharePoint.Workflow.Controls.Design;
using System.Collections.Generic;
using Microsoft.SharePoint.Utilities;
using System.Reflection;
using Microsoft.SharePoint;
using System.Web;
using System.Globalization;

namespace TPG.SharePoint.Workflow.Controls
{
    [Designer(typeof(ButtonSectionDesigner)),
    ToolboxData("<{0}:ButtonSection runat=\"server\"></{0}:ButtonSection>")]
    public class ButtonSection
        : FormSection
    {
        ITemplate _buttonTemplate;
        RepeatedControls _repeatedControls;

        // Section Line Row
        internal TableRow _sectionLineRow;
        internal TableCell _sectionLineCell;
        internal Button _defaultCancelButton;

        // Bottom Spacer Row
        TableRow _bottomSpacingRow;
        TableCell _bottomSpacingCell;
        Spacer _bottomSpacingSpacer;

        
        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ButtonSection)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate ButtonTemplate
        {
            get { return _buttonTemplate; }
            set
            {
                _buttonTemplate = value;
                _repeatedControls = null;
                ChildControlsCreated = false;
            }
        }

        [DefaultValue(false),
        Category("Appearance")]
        public bool TopButtons
        {
            get { return (bool?)ViewState["TopButtons"] ?? false; }
            set
            {
                if (value != TopButtons)
                {
                    ViewState["TopButtons"] = value;
                    if (ChildControlsCreated)
                    {
                        ApplySectionLineRowProperties();
                    }
                }
            }
        }

        [DefaultValue(true),
        Category("Appearance")]
        public bool ShowSectionLine
        {
            get { return (bool?)ViewState["ShowSectionLine"] ?? TopButtons == false; }
            set 
            {
                if (value != ShowSectionLine)
                {
                    ViewState["ShowSectionLine"] = value;
                    if (ChildControlsCreated)
                    {
                        ApplySectionLineRowProperties();
                    }
                }
            }
        }

        [DefaultValue(false),
        Category("Appearance")]
        public bool SmallSectionLine
        {
            get { return (bool?)ViewState["SmallSectionLine"] ?? false; }
            set 
            {
                if (value != SmallSectionLine)
                {
                    ViewState["SmallSectionLine"] = value;
                    if (ChildControlsCreated)
                    {
                        ApplySectionLineRowProperties();
                    }
                }
            }
        }

        public int BottomSpacing
        {
            get { return (int?)ViewState["BottomSpacing"] ?? 40; }
            set 
            {
                if (value != BottomSpacing)
                {
                    ViewState["BottomSpacing"] = value;
                    if (ChildControlsCreated)
                    {
                        ApplyBottomSpacingRowProperties();
                    }
                }
            }
        }

        public bool ShowStandardCancelButton
        {
            get { return (bool?)ViewState["ShowStandardCancelButton"] ?? true; }
            set 
            {
                ViewState["ShowStandardCancelButton"] = value;
                if (ChildControlsCreated)
                {
                    ApplyButtonRowProperties();
                }
            }
        }

        public short? CancelButtonTabIndex
        {
            get { return (short?)ViewState["CancelButtonTabIndex"]; }
            set
            {
                ViewState["CancelButtonTabIndex"] = value;
                if (ChildControlsCreated)
                {
                    ApplyButtonRowProperties();
                }
            }
        }

        protected internal int SectionLineHeight
        {
            get
            {
                return SmallSectionLine ? 1 : 2;
            }
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            Controls.Add(CreateSectionLineRow());
            Controls.Add(CreateTopSpacerRow());
            Controls.Add(CreateButtonContainerRow());
            Controls.Add(CreateBottomSpacerRow());
            ChildControlsCreated = true;
            ClearChildViewState();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            RenderChildren(writer);
        }

        protected override IDictionary GetDesignModeState()
        {
            IDictionary state = base.GetDesignModeState();
            state["ButtonTemplateContainer"] = _repeatedControls;
            return state;
        }

        TableRow CreateSectionLineRow()
        {
            _sectionLineRow = new TableRow();
            _sectionLineCell = new TableCell();
            Spacer spacer = new Spacer(1, 1);
            _sectionLineCell.CssClass = "ms-sectionline";
            _sectionLineCell.ColumnSpan = 2;
            _sectionLineRow.Cells.Add(_sectionLineCell);
            _sectionLineCell.Controls.Add(spacer);
            ApplySectionLineRowProperties();
            return _sectionLineRow;
        }

        TableRow CreateTopSpacerRow()
        {
            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            Spacer spacer = new Spacer(1, 10);
            cell.Height = Unit.Pixel(10);
            cell.CssClass = "ms-descriptiontext";
            cell.ColumnSpan = 2;
            row.Cells.Add(cell);
            cell.Controls.Add(spacer);
            return row;
        }

        TableRow CreateButtonContainerRow()
        {
            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            row.Cells.Add(cell);
            cell.Controls.Add(CreateInnerButtonContainer());
            cell.ColumnSpan = 2;
            return row;
        }

        Control CreateBottomSpacerRow()
        {
            _bottomSpacingRow = new TableRow();
            _bottomSpacingCell = new TableCell();
            _bottomSpacingSpacer = new Spacer();
            _bottomSpacingCell.ColumnSpan = 2;
            _bottomSpacingCell.Controls.Add(_bottomSpacingSpacer);
            _bottomSpacingRow.Cells.Add(_bottomSpacingCell);
            ApplyBottomSpacingRowProperties();
            return _bottomSpacingRow;
        }

        Table CreateInnerButtonContainer()
        {
            Table table = new Table();
            TableRow row = new TableRow();
            TableCell firstCell = new TableCell();
            LiteralControl firstCellContent = new LiteralControl("&nbsp;");
            TableCell buttonTemplateContainer = new TableCell();
            buttonTemplateContainer.Width = Unit.Percentage(1);
            buttonTemplateContainer.Wrap = false;            
            if (_repeatedControls == null)
            {
                _repeatedControls = new RepeatedControls();
                _repeatedControls.SeparatorHtml = @"<span id=""idSpace"" class=""ms-SpaceBetButtons""></span>";
                buttonTemplateContainer.Controls.Add(_repeatedControls);
                ITemplate template = _buttonTemplate;
                if (template != null)
                {
                    template.InstantiateIn(_repeatedControls);
                }
            }
            buttonTemplateContainer.Controls.Add(
                CreateDefaultCancelButton());
            table.CellPadding = 0;
            table.CellSpacing = 0;
            table.Width = Unit.Percentage(100);
            firstCell.Width = Unit.Percentage(99);
            table.Rows.Add(row);
            row.Cells.AddRange(new TableCell[] { firstCell, buttonTemplateContainer });
            firstCell.Controls.Add(firstCellContent);
            return table;
        }

        Button CreateDefaultCancelButton()
        {
            _defaultCancelButton = new DefaultCancelButton();
            _defaultCancelButton.Text = "Cancel";
            _defaultCancelButton.CssClass = "ms-ButtonHeightWidth";
            _defaultCancelButton.Attributes.Add(
                "accesskey", SPHttpUtility.HtmlEncode(
                    SPResource.GetString("wss,CancelButtonAccessKey", new object[0])));
            _defaultCancelButton.UseSubmitBehavior = false;
            _defaultCancelButton.Text =
                (string)HttpContext.GetGlobalResourceObject("wss", "multipages_cancelbutton_text");
            ApplyButtonRowProperties();
            return _defaultCancelButton;
        }

        void ApplyBottomSpacingRowProperties()
        {
            int bottomSpacing = BottomSpacing;
            _bottomSpacingRow.Visible = bottomSpacing > 0;
            _bottomSpacingCell.Height = bottomSpacing;
            _bottomSpacingSpacer.Width = new Unit(1);
            _bottomSpacingSpacer.Height = new Unit(bottomSpacing);
        }

        void ApplySectionLineRowProperties()
        {
            _sectionLineRow.Visible = ShowSectionLine;
            _sectionLineCell.Height = Unit.Pixel(SectionLineHeight);
        }

        void ApplyButtonRowProperties()
        {
            bool showStandardCancelButton = ShowStandardCancelButton;
            _defaultCancelButton.Visible = showStandardCancelButton;
            if (showStandardCancelButton && DesignMode == false)
            {
                if (String.Equals(
                    Page.Request.QueryString["CloseOnCancel"], 
                    "1", 
                    StringComparison.OrdinalIgnoreCase))
                {
                    _defaultCancelButton.OnClientClick = SPHttpUtility.NoEncode("window.close()");
                }
                else
                {
                    string proposedRedirectUrl = null;
                    PropertyInfo redirectProperty= Page.GetType().GetProperty("PageToRedirectOnCancel");
                    if(redirectProperty != null)
                    {
                        proposedRedirectUrl = (string)redirectProperty.GetValue(Page,null);
                    }
                    if (SPUtility.DetermineRedirectUrl(
                        proposedRedirectUrl, SPRedirectFlags.UseSource, Context, null, out proposedRedirectUrl) == false ||
                        String.IsNullOrEmpty(proposedRedirectUrl))
                    {
                        SPContext currentSPContext = SPContext.Current;
                        if (currentSPContext != null)
                        {

                            SiteMapNode siteMapNode = SiteMap.CurrentNode;
                            if (siteMapNode != null && siteMapNode.ParentNode != null)
                            {
                                proposedRedirectUrl = siteMapNode.ParentNode.Url;
                            }
                        }
                    }
                    if (String.IsNullOrEmpty(proposedRedirectUrl))
                    {
                        proposedRedirectUrl = SPContext.Current.Web.Url;
                    }
                    _defaultCancelButton.OnClientClick =
                        SPHttpUtility.NoEncode(
                            String.Format(
                                "window.location='{0}'",
                                SPHttpUtility.EcmaScriptStringLiteralEncode(proposedRedirectUrl)));
                }
                short? tabIndex = CancelButtonTabIndex;
                if (tabIndex != null)
                {
                    _defaultCancelButton.Attributes.Add(
                        "TabIndex", tabIndex.Value.ToString(CultureInfo.InvariantCulture));
                }
            }
        }

        class DefaultCancelButton
            : Button
        {
            protected override void AddAttributesToRender(HtmlTextWriter writer)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
                writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
                writer.AddAttribute(HtmlTextWriterAttribute.Value, Text);
                writer.AddAttribute(HtmlTextWriterAttribute.Onclick, OnClientClick);
                if (String.IsNullOrEmpty(Attributes["TabIndex"])== false)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, Attributes["TabIndex"]);
                }
            }
        }

        internal class RepeatedControls
            : WebControl
        {
            public string SeparatorHtml
            {
                get { return (string)ViewState["SeparatorHtml"] ?? String.Empty; }
                set { ViewState["SeparatorHtml"] = value; }
            }

            protected override void AddParsedSubObject(object obj)
            {
                LiteralControl literal = obj as LiteralControl;
                if (literal != null)
                {
                    return;
                }
                base.AddParsedSubObject(obj);
            }

            protected override void Render(HtmlTextWriter writer)
            {
                bool designMode = DesignMode;
                string separatorHtml = SeparatorHtml;
                if (designMode == true)
                {
                    base.AddAttributesToRender(writer);
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                }
                if (Controls.Count > 0)
                {
                    Controls[0].RenderControl(writer);
                    for (int i = 1; i < Controls.Count; i++)
                    {
                        writer.Write(separatorHtml);
                        Controls[i].RenderControl(writer);
                    }
                }
                if (designMode)
                {
                    writer.RenderEndTag();
                }
            }
        }
    }
}
